package com.ln.leetcode._1483;

import java.util.Arrays;

/**
 * 树节点的第 K 个祖先
 * <p>
 * 给你一棵树，树上有 n 个节点，按从 0 到 n-1 编号。树以父节点数组的形式给出，其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。
 * <p>
 * 树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。
 * <p>
 * 实现 TreeAncestor 类：
 * <p>
 * TreeAncestor（int n， int[] parent） 对树和父数组中的节点数初始化对象。
 * getKthAncestor(int node, int k) 返回节点 node 的第 k 个祖先节点。如果不存在这样的祖先节点，返回 -1 。
 * <p>
 * <p>
 * 示例 1：
 * 输入：
 * ["TreeAncestor","getKthAncestor","getKthAncestor","getKthAncestor"]
 * [[7,[-1,0,0,1,1,2,2]],[3,1],[5,2],[6,3]]
 * <p>
 * 输出：
 * [null,1,0,-1]
 * <p>
 * 解释：
 * TreeAncestor treeAncestor = new TreeAncestor(7, [-1, 0, 0, 1, 1, 2, 2]);
 * <p>
 * treeAncestor.getKthAncestor(3, 1);  // 返回 1 ，它是 3 的父节点
 * treeAncestor.getKthAncestor(5, 2);  // 返回 0 ，它是 5 的祖父节点
 * treeAncestor.getKthAncestor(6, 3);  // 返回 -1 因为不存在满足要求的祖先节点
 * <p>
 * <p>
 * 提示：
 * <p>
 * 1 <= k <= n <= 5 * 104
 * parent[0] == -1 表示编号为 0 的节点是根节点。
 * 对于所有的 0 < i < n ，0 <= parent[i] < n 总成立
 * 0 <= node < n
 * 至多查询 5 * 104 次
 */
public class TreeAncestor {

    // 最大深度
    private final static int MAX_LENGTH = 16;
    // 二维数组标识：第i个节点的第j个祖先是什么
    int ans[][];

    public TreeAncestor(int n, int[] parent) {
        // 定义共有n个节点，最大高度是 MAX_LENGTH
        ans = new int[n][MAX_LENGTH];
        // 初始化数据
        Arrays.stream(ans).forEach(a -> {
            Arrays.fill(a, -1);
        });

        // 初始化第1个父节点数据
        for (int i = 0; i < parent.length; i++) {
            ans[i][0] = parent[i];
        }

        // 倍增的思想
        for (int j = 0; j < MAX_LENGTH; j++) {
            for (int i = 0; i < n; i++) {
                //              0
                //            /   \
                //          1      2
                //        /   \   /   \
                //      3     4  5     6
                // ans[i][j] ==》 节点i的第j的祖先 ==》 节点i的第j-1的祖先的第j-1个祖先
                // ans[3][2] ==> 节点3的第二个祖先 ==》 节点3第一个祖先的第一个祖先 ==> ans[ans[3][1]][1] ==> ans[ans[3][2-1]][2-1]
                // ans[i][j] ==》 ans[ans[i][j-1]][j-1]
                if (ans[i][j - 1] != -1) {
                    ans[i][j] = ans[ans[i][j - 1]][j - 1];
                }
            }
        }
    }

    public int getKthAncestor(int node, int k) {
        for (int i = 0; i < MAX_LENGTH; i++) {
            // 找到对应的节点，
            if (((k >> i) & 1) != 0) {
                node = ans[node][i];
                if (node == -1) {
                    return -1;
                }
            }
        }
        return node;
    }
}
